package com.uniflow.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.uniflow.common.PageResult;
import com.uniflow.common.Result;
import com.uniflow.common.ResultCode;
import com.uniflow.entity.ApiKey;
import com.uniflow.service.ApiKeyService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * API密钥管理控制器
 * 
 * @author uniflow
 * @since 1.0.0
 */
@RestController
@RequestMapping("/api/v1/api-keys")
@Validated
@Api(tags = "API密钥管理")
public class ApiKeyController {
    
    @Autowired
    private ApiKeyService apiKeyService;
    
    /**
     * 分页查询API密钥列表
     */
    @GetMapping
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("分页查询API密钥列表")
    public Result<PageResult<ApiKey>> getKeyList(
            @ApiParam("页码") @RequestParam(defaultValue = "1") int pageNum,
            @ApiParam("页大小") @RequestParam(defaultValue = "10") int pageSize,
            @ApiParam("应用ID") @RequestParam(required = false) String appId,
            @ApiParam("访问密钥") @RequestParam(required = false) String accessKey,
            @ApiParam("是否过期") @RequestParam(required = false) Boolean expired) {
        try {
            IPage<ApiKey> page = apiKeyService.getKeyPage(pageNum, pageSize, appId, accessKey, expired);
            PageResult<ApiKey> result = new PageResult<ApiKey>(pageNum, pageSize, page.getTotal(), page.getRecords());
            return Result.success(result);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 根据ID查询API密钥详情
     */
    @GetMapping("/{id}")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("根据ID查询API密钥详情")
    public Result<ApiKey> getKeyById(@ApiParam("密钥ID") @PathVariable String id) {
        try {
            ApiKey apiKey = apiKeyService.getKeyWithApplication(id);
            if (apiKey == null) {
                return Result.error(ResultCode.NOT_FOUND, "API密钥不存在");
            }
            return Result.success(apiKey);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 根据访问密钥查询
     */
    @GetMapping("/access-key/{accessKey}")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("根据访问密钥查询")
    public Result<ApiKey> getKeyByAccessKey(@ApiParam("访问密钥") @PathVariable String accessKey) {
        try {
            ApiKey apiKey = apiKeyService.getKeyByAccessKey(accessKey);
            if (apiKey == null) {
                return Result.error(ResultCode.NOT_FOUND, "API密钥不存在");
            }
            return Result.success(apiKey);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 根据应用ID查询密钥列表
     */
    @GetMapping("/app/{appId}")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("根据应用ID查询密钥列表")
    public Result<List<ApiKey>> getKeysByAppId(@ApiParam("应用ID") @PathVariable String appId) {
        try {
            List<ApiKey> keys = apiKeyService.getKeysByAppId(appId);
            return Result.success(keys);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询有效的密钥
     */
    @GetMapping("/valid/{appId}")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询有效的密钥")
    public Result<List<ApiKey>> getValidKeys(@ApiParam("应用ID") @PathVariable String appId) {
        try {
            List<ApiKey> keys = apiKeyService.getValidKeys(appId);
            return Result.success(keys);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询过期的密钥
     */
    @GetMapping("/expired")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询过期的密钥")
    public Result<List<ApiKey>> getExpiredKeys() {
        try {
            List<ApiKey> keys = apiKeyService.getExpiredKeys();
            return Result.success(keys);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询即将过期的密钥
     */
    @GetMapping("/expiring")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询即将过期的密钥")
    public Result<List<ApiKey>> getExpiringKeys(
            @ApiParam("天数") @RequestParam(defaultValue = "7") Integer days) {
        try {
            List<ApiKey> keys = apiKeyService.getExpiringKeys(days);
            return Result.success(keys);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 创建API密钥
     */
    @PostMapping
    @PreAuthorize("hasAuthority('api_key:write')")
    @ApiOperation("创建API密钥")
    public Result<ApiKey> createKey(@Valid @RequestBody CreateKeyRequest request) {
        try {
            ApiKey apiKey = new ApiKey();
            apiKey.setAppId(request.getAppId());
            apiKey.setPermissions(request.getPermissions());
            apiKey.setExpiresAt(request.getExpiresAt());
            
            ApiKey createdKey = apiKeyService.createKey(apiKey);
            return Result.success(createdKey);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 更新密钥过期时间
     */
    @PutMapping("/{id}/expires")
    @PreAuthorize("hasAuthority('api_key:write')")
    @ApiOperation("更新密钥过期时间")
    public Result<Void> updateExpiresAt(
            @ApiParam("密钥ID") @PathVariable String id,
            @RequestBody UpdateExpiresRequest request) {
        try {
            apiKeyService.updateExpiresAt(id, request.getExpiresAt());
            return Result.success();
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 更新密钥权限
     */
    @PutMapping("/{id}/permissions")
    @PreAuthorize("hasAuthority('api_key:write')")
    @ApiOperation("更新密钥权限")
    public Result<Void> updatePermissions(
            @ApiParam("密钥ID") @PathVariable String id,
            @RequestBody UpdatePermissionsRequest request) {
        try {
            apiKeyService.updatePermissions(id, request.getPermissions());
            return Result.success();
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 删除API密钥
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('api_key:write')")
    @ApiOperation("删除API密钥")
    public Result<Void> deleteKey(@ApiParam("密钥ID") @PathVariable String id) {
        try {
            apiKeyService.deleteKey(id);
            return Result.success();
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 批量删除过期密钥
     */
    @DeleteMapping("/expired/cleanup")
    @PreAuthorize("hasAuthority('api_key:write')")
    @ApiOperation("批量删除过期密钥")
    public Result<Map<String, Object>> deleteExpiredKeys() {
        try {
            int deletedCount = apiKeyService.deleteExpiredKeys();
            Map<String, Object> result = new HashMap<>();
            result.put("deletedCount", deletedCount);
            return Result.success(result);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询密钥统计信息
     */
    @GetMapping("/stats")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询密钥统计信息")
    public Result<Map<String, Object>> getKeyStats() {
        try {
            Map<String, Object> stats = new HashMap<>();
            stats.put("totalCount", apiKeyService.getTotalCount());
            stats.put("validCount", apiKeyService.getValidCount());
            stats.put("expiredCount", apiKeyService.getExpiredCount());
            stats.put("todayNewCount", apiKeyService.getTodayNewCount());
            return Result.success(stats);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询密钥使用统计
     */
    @GetMapping("/{id}/usage")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询密钥使用统计")
    public Result<List<Map<String, Object>>> getUsageStats(
            @ApiParam("密钥ID") @PathVariable String id,
            @ApiParam("开始日期") @RequestParam(required = false) String startDate,
            @ApiParam("结束日期") @RequestParam(required = false) String endDate) {
        try {
            List<Map<String, Object>> stats = apiKeyService.getUsageStats(id, startDate, endDate);
            return Result.success(stats);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询密钥调用频率统计
     */
    @GetMapping("/stats/call-frequency")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询密钥调用频率统计")
    public Result<List<Map<String, Object>>> getCallFrequencyStats() {
        try {
            List<Map<String, Object>> stats = apiKeyService.getCallFrequencyStats();
            return Result.success(stats);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询密钥权限分布
     */
    @GetMapping("/stats/permission-distribution")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询密钥权限分布")
    public Result<List<Map<String, Object>>> getPermissionDistribution() {
        try {
            List<Map<String, Object>> distribution = apiKeyService.getPermissionDistribution();
            return Result.success(distribution);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询密钥生命周期统计
     */
    @GetMapping("/stats/lifecycle")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询密钥生命周期统计")
    public Result<List<Map<String, Object>>> getLifecycleStats() {
        try {
            List<Map<String, Object>> stats = apiKeyService.getLifecycleStats();
            return Result.success(stats);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询最近活跃的密钥
     */
    @GetMapping("/recent-active")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询最近活跃的密钥")
    public Result<List<ApiKey>> getRecentActiveKeys(
            @ApiParam("限制数量") @RequestParam(defaultValue = "10") Integer limit) {
        try {
            List<ApiKey> keys = apiKeyService.getRecentActiveKeys(limit);
            return Result.success(keys);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询长时间未使用的密钥
     */
    @GetMapping("/inactive")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询长时间未使用的密钥")
    public Result<List<ApiKey>> getInactiveKeys(
            @ApiParam("天数") @RequestParam(defaultValue = "30") Integer days) {
        try {
            List<ApiKey> keys = apiKeyService.getInactiveKeys(days);
            return Result.success(keys);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询高频使用的密钥
     */
    @GetMapping("/high-frequency")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询高频使用的密钥")
    public Result<List<ApiKey>> getHighFrequencyKeys(
            @ApiParam("限制数量") @RequestParam(defaultValue = "10") Integer limit) {
        try {
            List<ApiKey> keys = apiKeyService.getHighFrequencyKeys(limit);
            return Result.success(keys);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询密钥安全统计
     */
    @GetMapping("/{id}/security")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询密钥安全统计")
    public Result<Map<String, Object>> getSecurityStats(@ApiParam("密钥ID") @PathVariable String id) {
        try {
            Map<String, Object> stats = apiKeyService.getSecurityStats(id);
            return Result.success(stats);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询密钥错误统计
     */
    @GetMapping("/{id}/errors")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询密钥错误统计")
    public Result<List<Map<String, Object>>> getErrorStats(@ApiParam("密钥ID") @PathVariable String id) {
        try {
            List<Map<String, Object>> stats = apiKeyService.getErrorStats(id);
            return Result.success(stats);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询密钥性能统计
     */
    @GetMapping("/{id}/performance")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询密钥性能统计")
    public Result<Map<String, Object>> getPerformanceStats(@ApiParam("密钥ID") @PathVariable String id) {
        try {
            Map<String, Object> stats = apiKeyService.getPerformanceStats(id);
            return Result.success(stats);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询密钥IP访问统计
     */
    @GetMapping("/{id}/ip-access")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询密钥IP访问统计")
    public Result<List<Map<String, Object>>> getIpAccessStats(@ApiParam("密钥ID") @PathVariable String id) {
        try {
            List<Map<String, Object>> stats = apiKeyService.getIpAccessStats(id);
            return Result.success(stats);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询密钥时段访问统计
     */
    @GetMapping("/{id}/hourly-access")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询密钥时段访问统计")
    public Result<List<Map<String, Object>>> getHourlyAccessStats(@ApiParam("密钥ID") @PathVariable String id) {
        try {
            List<Map<String, Object>> stats = apiKeyService.getHourlyAccessStats(id);
            return Result.success(stats);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询密钥月度统计
     */
    @GetMapping("/{id}/monthly")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询密钥月度统计")
    public Result<List<Map<String, Object>>> getMonthlyStats(
            @ApiParam("密钥ID") @PathVariable String id,
            @ApiParam("月数") @RequestParam(defaultValue = "6") Integer months) {
        try {
            List<Map<String, Object>> stats = apiKeyService.getMonthlyStats(id, months);
            return Result.success(stats);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 验证密钥和应用的关联关系
     */
    @GetMapping("/validate/{accessKey}/{appId}")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("验证密钥和应用的关联关系")
    public Result<Boolean> validateKeyAppRelation(
            @ApiParam("访问密钥") @PathVariable String accessKey,
            @ApiParam("应用ID") @PathVariable String appId) {
        try {
            boolean valid = apiKeyService.validateKeyAppRelation(accessKey, appId);
            return Result.success(valid);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 查询密钥的权限列表
     */
    @GetMapping("/permissions/{accessKey}")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("查询密钥的权限列表")
    public Result<List<String>> getKeyPermissions(@ApiParam("访问密钥") @PathVariable String accessKey) {
        try {
            List<String> permissions = apiKeyService.getKeyPermissions(accessKey);
            return Result.success(permissions);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    /**
     * 检查密钥是否有指定权限
     */
    @GetMapping("/check-permission/{accessKey}/{permission}")
    @PreAuthorize("hasAuthority('api_key:read')")
    @ApiOperation("检查密钥是否有指定权限")
    public Result<Boolean> hasPermission(
            @ApiParam("访问密钥") @PathVariable String accessKey,
            @ApiParam("权限") @PathVariable String permission) {
        try {
            boolean hasPermission = apiKeyService.hasPermission(accessKey, permission);
            return Result.success(hasPermission);
        } catch (Exception e) {
            return Result.error(ResultCode.ERROR, e.getMessage());
        }
    }
    
    // ==================== 请求数据结构 ====================
    
    public static class CreateKeyRequest {
        @NotBlank(message = "应用ID不能为空")
        private String appId;
        
        private String permissions;
        
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime expiresAt;
        
        // getters and setters
        public String getAppId() { return appId; }
        public void setAppId(String appId) { this.appId = appId; }
        public String getPermissions() { return permissions; }
        public void setPermissions(String permissions) { this.permissions = permissions; }
        public LocalDateTime getExpiresAt() { return expiresAt; }
        public void setExpiresAt(LocalDateTime expiresAt) { this.expiresAt = expiresAt; }
    }
    
    public static class UpdateExpiresRequest {
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
        private LocalDateTime expiresAt;
        
        // getters and setters
        public LocalDateTime getExpiresAt() { return expiresAt; }
        public void setExpiresAt(LocalDateTime expiresAt) { this.expiresAt = expiresAt; }
    }
    
    public static class UpdatePermissionsRequest {
        private String permissions;
        
        // getters and setters
        public String getPermissions() { return permissions; }
        public void setPermissions(String permissions) { this.permissions = permissions; }
    }
}